<template>
  <div class="article-list">
    <van-pull-refresh
      v-model="loadingOfRefresh"
      @refresh="onRefresh"
      :success-text="refreshFinishedText"
      :success-duration="1500"
      :disabled="disabledPullRefresh"
    >
      <!-- v-model =就是=> v-on:input 和 v-bind:value 的组合 -->
      <!-- :error.sync="error" =就是=> :error="error" 和 @update:error="error = $event" 的简写形式 -->
      <van-list
        ref="refVanList"
        @load="onLoad"
        v-model="loading"
        :finished="finished"
        finished-text="我是有底线的"
        :error.sync="error"
        error-text="加载失败，请点击重试。"
      >
        <!-- <van-cell v-for="(v, i) of list" :key="i" :title="v.title" /> -->
          <!-- @click="$router.push('/article/' + v.art_id)" -->
        <ArticleListItem
          v-for="(v, i) of list" :key="i" :article="v"
          @click.native="$router.push({ name: 'article', params: { id: v.art_id } })"
        />
      </van-list>
    </van-pull-refresh>
  </div>
</template>

<script>
import ArticleListItem from '../article-list-item'
export default {
  name: 'ArticleList',
  components: { ArticleListItem },
  // props: ['channel', 'keywords', 'disabledPullRefresh'],
  props: {
    channel: Object,
    keywords: String,
    // 对象形式定义的属性，如果类型为布尔值，默认值为 false，那么在传递这个属性的时候，只要写上属性名即可
    // 比如：<ArticleList :keywords="keywords" disabledPullRefresh />
    disabledPullRefresh: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      currentPage: 1, // 搜索时 - 当前页面
      refreshFinishedText: '刷新成功', // 用来做刷新完成后的提示文本，包括成功和失败
      loadingOfRefresh: false, // 刷新的加载中开关
      error: false,
      timestamp: Date.now(),
      list: [], // 文章列表数据
      loading: false,
      finished: false
    }
  },
  methods: {
    onRefresh () {
      // 如果刷新，将 loading 改成 true，这样加载完成后 loading 会变成 false，
      // 就会触发 van-list 组件的是否填满容器的检查动作（当 loading 从 true 变成 false 时）
      this.loading = true
      this.timestamp = Date.now()
      this.onLoad(true).then((results) => {
        // this.refreshFinishedText = `刷新成功，加载了${results.length}条文章`
        this.refreshFinishedText = '刷新成功'
      }, () => {
        this.refreshFinishedText = '刷新失败，请下拉重试！'
      }).finally(() => {
        this.loadingOfRefresh = false
      })
    },
    // isRefresh 表示是否为刷新动作，默认 false
    onLoad (isRefresh = false) {
      if (this.keywords) {
        // 搜索页面过来的
        return this.apis.article.search({ page: this.currentPage, per_page: 10, q: this.keywords }).then(list => {
          this.list.push(...list)
          if (list.length === 0) {
            this.finished = true
          } else {
            this.currentPage++
          }
        }, (err) => {
          this.error = true
          // return [1, 2, 3]
          throw err // 为了不让下一次 .then 进入成功的回调
        }).finally(() => {
          // 不管成功还是失败，都会执行到这里
          this.loading = false
        })
      }
      // 首页使用的
      return this.apis.article.getArticles({ channel_id: this.channel.id, timestamp: this.timestamp })
        .then((res) => {
          // if (Math.random() > 0.5) {
          //   throw new Error('模拟错误')
          // }
          return res
        })
        // .then 函数接收的两个参数，一个是成功回调，一个是失败回调
        // 而且有默认值处理，
        // function then(onResolved, onRejected) {
        //   if (onResolved === undefined) onResolved = res => res
        //   if (onRejected === undefined) onRejected = err => { throw err }
        //   .then 链式调用的异常穿透，就是上面这个 onRejected 默认值逻辑
        // }
        .then()
        .then()
        .then()
        .then()
        .then()
        .then()
        .then(res => {
          const { results, pre_timestamp: preTimestamp } = res.data.data

          // 备注：已移入 @/api 接口函数中
          // // 过滤无效图片
          // // 先映射所有的文章对象
          // results.map(v => {
          //   // 判断是否有图片
          //   if (v.cover.type !== 0) {
          //     // 如果有，则将满足图片链接地址条件的过滤出来，重新赋值给 文章对象的 images 数组
          //     v.cover.images = v.cover.images.filter(v2 => v2.startsWith('http://geek.itheima.net/resources/images/'))
          //   }
          //   // 返回这个文章对象
          //   return v
          // })
          // // /过滤无效图片

          // 数据的变异方法和非变异方法的区别：
          // 变异方法：调用完该方法后，原数组会发生变化
          // - push pop unshift shift splice sort reverse
          // 非变异方法：调用完该方法后，原数组不会发生变化
          // - forEach map filter reduce find findIndex every some slice join concat includes indexOf
          // results.splice(3)
          // 要做一层判断，如果是刷新，应该 unshift，否在才是 push
          if (isRefresh) {
            // this.list.unshift(...results)
            this.list = results
            // 为啥 Vue 要将视图的更新变成异步的？
            // 因为 对于一个数据而言，在代码执行过程中，有可能会被修改很多次：
            // 比如：第1次 ==> this.msg = 'a'
            // 比如：第2次 ==> this.msg = 'b'
            // 比如：第3次 ==> this.msg = 'c'
            // 对于上面的三次修改数据，其实用户最终页面上只会显示最后那个 c，前面两次完全没有必要去更新页面，
            // 这样可以减少对 dom 的操作
            // this.$refs.refVanList.check() // 如果检测到没有铺满，会继续触发 load 事件
            // this.$nextTick(() => this.$refs.refVanList.check())
            // 还有一种静态方法调用方式，当拿不到组件实例时，可以使用：Vue.nextTick
          } else {
            this.list.push(...results)
          }
          if (results.length === 0) {
            this.finished = true
          } else {
            this.timestamp = preTimestamp
          }
          return results // 这里 return 的数据，在下一次 .then 时可以获取到
        }, (err) => {
          // 进入到这里来，除非你继续向后抛错误，否则当前的状态会为 成功
          this.error = true
          // return [1, 2, 3]
          throw err
          // eslint-disable-next-line no-throw-literal
          // throw [err, [1, 2, 3]]
          // return Promise.reject(err)
        }).finally(() => {
          // 不管成功还是失败，都会执行到这里
          this.loading = false
        })
    }
  }
}
</script>

<style>
/* .article-list { */
  /* calc =MDN=> https://developer.mozilla.org/zh-CN/docs/Web/CSS/calc  */
  /* height: calc(100vh - 180px - 100px);
  overflow-y: auto; */
/* } */
</style>
